package com.yykj.order.center.server.repository;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.github.pagehelper.Page;
import com.yykj.order.center.client.dto.ConsultationDoctorRankingDto;
import com.yykj.order.center.client.form.consultation.ConsultationAdminListForm;
import com.yykj.order.center.server.entity.Consultation;
import com.yykj.order.center.server.enums.ConsultationDoctorStatus;
import com.yykj.order.center.server.exception.ErrorCode;
import com.yykj.order.center.server.exception.ErrorCodeException;
import com.yykj.order.center.server.util.StringUtil;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.SelectProvider;
import org.apache.ibatis.jdbc.SQL;
import org.springframework.stereotype.Repository;

import java.util.List;

@Mapper
@Repository
public interface ConsultationMapper extends BaseMapper<Consultation> {


    @SelectProvider(type = ConsultationMapperProvider.class, method = "selectByDoctor")
    Page<Consultation> selectByDoctor(@Param("doctorId") String doctorId, @Param("status") Integer status);

    default Consultation findById(String consultationId) {
        Consultation consultation = this.selectById(consultationId);
        if (consultation == null) {
            throw new ErrorCodeException(ErrorCode._1001);
        }
        return consultation;
    }

    @SelectProvider(type = ConsultationMapperProvider.class, method = "calcConsultationDoctorRanking")
    List<ConsultationDoctorRankingDto> calcConsultationDoctorRanking(@Param("doctorId") String doctorId);

    default Page<Consultation> findList(ConsultationAdminListForm consultationAdminListForm) {
        LambdaQueryWrapper<Consultation> q = new LambdaQueryWrapper<>();
        String applyDoctorId = consultationAdminListForm.getDoctorId();
        String applyHospitalId = consultationAdminListForm.getHospitalId();
        String patientMedicalNo = consultationAdminListForm.getPatientMedicalNo();
        String patientMobile = consultationAdminListForm.getPatientMobile();
        String patientName = consultationAdminListForm.getPatientName();
        Integer status = consultationAdminListForm.getStatus();
        String applyDoctorName = consultationAdminListForm.getDoctorName();
        String applyHospitalDepartmentId = consultationAdminListForm.getDepartmentId();
        if (StringUtil.isNotBlank(applyDoctorId)) {
            q.eq(Consultation::getApplyDoctorId, applyDoctorId);
        }
        if (StringUtil.isNotBlank(applyHospitalId)) {
            q.eq(Consultation::getApplyDoctorHospitalId, applyHospitalId);
        }
        if (StringUtil.isNotBlank(applyHospitalDepartmentId)) {
            q.eq(Consultation::getApplyDoctorDepartmentId, applyHospitalDepartmentId);
        }
        if (StringUtil.isNotBlank(patientMedicalNo)) {
            q.like(Consultation::getPatientMedicalNo, patientMedicalNo);
        }
        if (StringUtil.isNotBlank(patientMobile)) {
            q.eq(Consultation::getPatientMobile, patientMobile);
        }
        if (StringUtil.isNotBlank(patientName)) {
            q.like(Consultation::getPatientName, patientName);
        }
        if (StringUtil.isNotBlank(consultationAdminListForm.getStartTime())) {
            q.gt(Consultation::getAddtime, StringUtil.dateToTimeStamp(consultationAdminListForm.getStartTime()));
        }
        if (StringUtil.isNotBlank(consultationAdminListForm.getEndTime())) {
            q.lt(Consultation::getAddtime, StringUtil.dateToTimeStamp(consultationAdminListForm.getEndTime()));
        }
        if (StringUtil.isNotBlank(applyDoctorName)) {
            q.like(Consultation::getApplyDoctorName, applyDoctorName);
        }
        if (status != null) {
            q.eq(Consultation::getStatus, status);
        }
        q.orderByDesc(Consultation::getAddtime);
        return (Page) this.selectList(q);
    }

    @Select({"select * from core_consultation where group_im_id = #{groupImId} limit 1"})
    Consultation findByGroupImId(String groupImId);

    default int countByDoctor(String doctorId, int startTime, int endTime) {
        LambdaQueryWrapper<Consultation> c = new LambdaQueryWrapper<>();
        c.eq(Consultation::getApplyDoctorId, doctorId);
        if (startTime > 0) {
            c.gt(Consultation::getAddtime, startTime);
        }
        if (startTime > 0) {
            c.lt(Consultation::getAddtime, endTime);
        }
        return this.selectCount(c);
    }

    class ConsultationMapperProvider {
        public String calcConsultationDoctorRanking(@Param("doctorId") String doctorId) {
            SQL sql = new SQL();
            sql.SELECT("a.*,count(*) as times")
                    .FROM(" core_consultation_doctor a LEFT JOIN core_consultation b on a.consultation_id = b.id")
                    .WHERE("b.apply_doctor_id = #{doctorId}")
                    .GROUP_BY("doctor_id")
                    .ORDER_BY("count(*) desc,a.addtime desc");
            return sql.toString();
        }

        public String selectByDoctor(@Param("doctorId") String doctorId, @Param("status") Integer status) {
            StringBuilder doctorStatus = new StringBuilder();
            doctorStatus.append(ConsultationDoctorStatus.success).append(",").append(ConsultationDoctorStatus.reviewSuccess);
            StringBuilder sb = new StringBuilder();
            sb.append("SELECT c.* from ")
                    .append("(")
                    .append("SELECT * from core_consultation where apply_doctor_id = #{doctorId}");

            if (status != null) {
                if (status == 1) {
                    sb.append(" and status in (").append(doctorStatus).append(")");
                } else if (status != 0) {
                    sb.append(" and status = #{status} ");
                }
            }
            sb.append(" union all")
                    .append(" SELECT b.* from core_consultation_doctor a LEFT JOIN core_consultation b on a.consultation_id = b.id")
                    .append(" where a.doctor_id = #{doctorId} and a.status in (").append(doctorStatus).append(")");
            if (status != null) {
                if (status == 1) {
                    sb.append(" and b.status in (").append(doctorStatus).append(")");
                } else if (status != 0) {
                    sb.append(" and b.status = #{status} ");
                }
            }
            sb.append(") c order by c.addtime desc ");
            return sb.toString();
        }
    }
}
